package logic

import (
	"context"
	"encoding/json"
	"errors"
	"log"
	"strconv"
	"strings"
	"time"
	"yundian/internel/app/dao"
	"yundian/internel/app/dao/memberdao"
	"yundian/internel/app/dao/userdao"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/helper/resphelper/userresp"
	"yundian/internel/app/models/devices"
	"yundian/internel/app/models/loginlogs"
	"yundian/internel/app/models/membermodel"
	Menus "yundian/internel/app/models/menus"
	"yundian/internel/app/models/orders"
	Permissions "yundian/internel/app/models/permissions"
	"yundian/internel/app/models/roles"
	"yundian/internel/app/models/users"
	"yundian/internel/pkg/authorized"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
	"yundian/internel/pkg/dingo/result"
	"yundian/internel/pkg/utils"
)

// ------------- 逻辑层logic - 权限相关 ------------------//

type AuthLogic struct {
}

func NewAuthLogic() *AuthLogic {
	return &AuthLogic{}
}

type LoginInfo struct {
	TokenKey    string
	LoginDesc   string
}

/**
 * UserLogin 登录业务逻辑
 * @phone 登录手机号
 * @password 登录密码
 * @ip 登录IP
 * @platform 登录平台
 */
func (l *AuthLogic) UserLogin(phone, password, ip, platform string) (token string, err error) {
	loginTime := dingo.Time(time.Now().Unix())
	user := dao.NewUserDao().GetUserInfoFromPhone(phone).Unwrap().(*users.UserModel)
	loginInfo := l.GetLoginInfoByPlatform(platform, user.ID)

	if user.ID == 0 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, loginInfo.LoginDesc, "用户名错误", phone)
		return "", errors.New("用户名密码错误") // 用户名不存在
	}
	if user.Status == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, loginInfo.LoginDesc, "帐户已被禁用", phone)
		return "", errors.New("该帐户已被禁用") // 用户已被禁用
	}
	if user.IsDelete == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, loginInfo.LoginDesc, "帐号已弃用", phone)
		return "", errors.New("该帐户已弃用，请联系管理员恢复") // 已删除
	}
	if user.Password != utils.EncryptPassword(password) {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, loginInfo.LoginDesc, "密码错误", phone)
		return "", errors.New("用户名密码错误") // 密码错误
	}
	// 判断 可登录的平台
	log.Println("打印测试-----平台", strings.Split(user.Platform, ","), platform)
	if !helper.InSlice(strings.Split(user.Platform, ","), platform) {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, loginInfo.LoginDesc, "无平台登录权限", phone)
		return "", errors.New("无平台登录权限，请联系管理员")
	}
	// 商户不可登录PC后台(客房管家后台除外)
	if platform != "hotel" && user.IsAdmin == 3 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, loginInfo.LoginDesc, "无平台登录权限", phone)
		return "", errors.New("无平台登录权限，请联系管理员")
	}
	// 生成 Token
	token, err = dingo.GenerateToken(user.ID, user.UserName, user.IsAdmin, user.ParentID, user.IsPlace, user.IsDraw, platform)
	global.Rdb.Set(context.Background(), loginInfo.TokenKey, token, time.Hour*4) // 过期时间4小时

	dingo.Task(l.updateUserLoginInfo, func() {}, user.ID, ip, loginTime)                    // 更新登录信息
	dingo.Task(l.updateUserLoginCount, func() {}, user.ID)                                  // 更新登录次数
	dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, loginInfo.LoginDesc, "登录成功", phone) // 记录登录日志
	return
}

// GetTokenPreByPlatform 根据平台登录获取token前缀
func (l *AuthLogic) GetLoginInfoByPlatform(platform string, id int) LoginInfo {
	var key, loginDesc string
	switch platform {
	case "zmadmin": // 密码线充
		key = utils.Join(global.Const.Pre.TokenKeyPre, "-zmadmin-Login-Token-", strconv.Itoa(id))
		loginDesc = "密码线充"
	case "hotel": // 客房管家
		key = utils.Join(global.Const.Pre.TokenKeyPre, "-hotel-Login-Token-", strconv.Itoa(id))
		loginDesc = "客房管家"
	case "om": // 中台运营
		key = utils.Join(global.Const.Pre.TokenKeyPre, "-om-Login-Token-", strconv.Itoa(id))
		loginDesc = "中台运营"
	case "wifi": // 共享WIFI
		key = utils.Join(global.Const.Pre.TokenKeyPre, "-wiif-Login-Token-", strconv.Itoa(id))
		loginDesc = "共享WIFI"
	case "msc": // 供应商平台
		key = utils.Join(global.Const.Pre.TokenKeyPre, "-msc-Login-Token-", strconv.Itoa(id))
		loginDesc = "供应商"
	case "xm": // 小曼到家平台
		key = utils.Join(global.Const.Pre.TokenKeyPre, "-xm-Login-Token-", strconv.Itoa(id))
		loginDesc = "小曼到家"
	}

	return LoginInfo{
		TokenKey:key,
		LoginDesc: loginDesc,
	}
}






func (l *AuthLogic) UserMerchantLogin(phone, password, ip, t string) (token string, err error) {
	loginTime := dingo.Time(time.Now().Unix())
	user := dao.NewUserDao().GetUserInfoFromPhone(phone).Unwrap().(*users.UserModel)

	if user.ID == 0 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录", "用户名错误", phone)
		return "", errors.New("用户名密码错误") // 用户名不存在
	}
	if user.Status == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录", "帐户已被禁用", phone)
		return "", errors.New("该帐户已被禁用") // 用户已被禁用
	}
	//if user.IsAdmin == helper.TypeNumIsAdminAgent {
	//	dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录", "不允许商户在后台登录", phone)
	//	return "", errors.New("非法登录") // 用户已被禁用
	//}
	//if user.IsAdmin == 3 && user.IsPlace == 1 || user.IsPlace == 2 { // 商户、老板不可以登录 //is_place == 3 是KA用户
	//	dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录", "不允许商户在后台登录", phone)
	//	return "", errors.New("非法登录") // 用户已被禁用
	//}
	if user.IsDelete == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录", "帐号已弃用", phone)
		return "", errors.New("该帐户已弃用，请联系管理员恢复") // 已删除
	}
	if user.Password != utils.EncryptPassword(password) {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录", "密码错误", phone)
		return "", errors.New("用户名密码错误") // 密码错误
	}

	// 生成 Token
	//key := utils.Join("YdLogin-Token", strconv.Itoa(user.ID))
	key := utils.Join("YdLogin-Token", strconv.Itoa(user.ID), t)
	token, err = dingo.GenerateToken(user.ID, user.UserName, user.IsAdmin, user.ParentID, user.IsPlace, user.IsDraw, "")
	global.Rdb.Set(context.Background(), key, token, time.Hour*24*7) // 过期时间

	dingo.Task(l.updateUserLoginInfo, func() {}, user.ID, ip, loginTime)                    // 更新登录信息
	dingo.Task(l.updateUserLoginCount, func() {}, user.ID)                                  // 更新登录次数
	dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录", "登录成功", phone) // 记录登录日志
	return
}

func (l *AuthLogic) UserMerchantStewardLogin(phone, password, ip, t string) (token string, err error) {
	loginTime := dingo.Time(time.Now().Unix())
	user := dao.NewUserDao().GetUserInfoFromPhone(phone).Unwrap().(*users.UserModel)

	if user.ID == 0 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录-客房管家", "用户名错误", phone)
		return "", errors.New("用户名密码错误") // 用户名不存在
	}
	if user.Status == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录-客房管家", "帐户已被禁用", phone)
		return "", errors.New("该帐户已被禁用") // 用户已被禁用
	}
	if user.IsDelete == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录-客房管家", "帐号已弃用", phone)
		return "", errors.New("该帐户已弃用，请联系管理员恢复") // 已删除
	}
	if user.IsSteward != 1 && !helper.IsAdminAndStaff(user.IsAdmin, user.ParentID) {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录-客房管家", "未开通WIFI服务", phone)
		return "", errors.New("请联系管理员开通服务")
	}
	if user.Password != utils.EncryptPassword(password) {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录-客房管家", "密码错误", phone)
		return "", errors.New("用户名密码错误") // 密码错误
	}

	// 生成 Token
	//key := utils.Join("YdLogin-Token", strconv.Itoa(user.ID))
	key := utils.Join("YdLogin-Token", strconv.Itoa(user.ID), t)
	token, err = dingo.GenerateToken(user.ID, user.UserName, user.IsAdmin, user.ParentID, user.IsPlace, user.IsDraw, "")
	global.Rdb.Set(context.Background(), key, token, time.Hour*24*7) // 过期时间

	dingo.Task(l.updateUserLoginInfo, func() {}, user.ID, ip, loginTime)                    // 更新登录信息
	dingo.Task(l.updateUserLoginCount, func() {}, user.ID)                                  // 更新登录次数
	dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "后台登录-wifi", "登录成功", phone) // 记录登录日志
	return
}

// UpdateUserLoginInfo 更新登录信息 (登录IP、登录时间)
func (l *AuthLogic) updateUserLoginInfo(params ...interface{}) {
	id := params[0].(int)
	ip := params[1].(string)
	t := params[2].(dingo.Time)
	dao.NewUserDao().UpdateUserLoginInfo(id, ip, t).Unwrap()
}

func (l *AuthLogic) updateUserLoginCount(params ...interface{}) {
	id := params[0].(int) // 用户ID
	dao.NewUserDao().UpdateUserLoginCount(id).Unwrap()
}

// InsertUserLoginLog 记录登录日志
func (l *AuthLogic) insertUserLoginLog(params ...interface{}) {
	userModel := params[0].(*users.UserModel)
	ip := params[1].(string)
	t := params[2].(dingo.Time)
	module := params[3].(string)
	desc := params[4].(string)
	phone := params[5].(string)

	lgoinLogModel := loginlogs.LoginLogsModel{
		LoginTime: t,
		LoginIp:   ip,
		UserId:    userModel.ID,
		IsAdmin:   userModel.IsAdmin,
		UserName:  userModel.Name,
		CreateAt:  dingo.Time(time.Now().Unix()),
		Module:    module,
		Desc:      desc,
		Phone:     phone,
	}

	//lgoinLogModel := loginlogs.New()
	dao.NewLoginLogsDao().InsertLoginLogs(&lgoinLogModel).Unwrap()
}

// {
//  'id': 1,
//  'name': 'yundian',
//  'role': {
//            'id': 'admin',
//            'name': '管理员',
//            'permissions': {
//                            'permissionId': 'dashboard',
//                            'permissionName': '仪表盘',
//                            'actions': '[{"action":"add","defaultCheck":false,"describe":"新增"}]',
//            }
//   }
// }
// GetUserInfo 获取用户信息业务逻辑
func (l *AuthLogic) GetUserInfo(uid int) (userInfo *users.UserInfoWithLogin) {
	var permissionList []*Permissions.PsermissionWithActionList
	// 获取用户信息   (用户与角色 1对1的关系)
	userInfo = dao.NewUserDao().GetUserInfoFromId(uid).Unwrap().(*users.UserInfoWithLogin)
	// 获取角色信息
	roleInfo := dao.NewRoleDao().GetRoleInfoFromId(userInfo.RoleId).Unwrap().(*roles.RoleWithLogin)
	// 获取角色下的权限信息
	permissionList = dao.NewPermissionDao().GetPermissionsFromRoleId(userInfo.RoleId).Unwrap().([]*Permissions.PsermissionWithActionList)

	// 抽单用户可拥有奖励订单查看权限
	if userInfo.IsDraw == 1 {
		drawPermissionList := dao.NewPermissionDao().GetPermissionsByLabel("takeorderlist").Unwrap().(*Permissions.PsermissionWithActionList)
		permissionList = append(permissionList, drawPermissionList)
	}

	// 大客户拥有普通订单查看权限
	if userInfo.IsKa == 1 {
		normalOrderPermissionList := dao.NewPermissionDao().GetPermissionsByLabel("orderlist").Unwrap().(*Permissions.PsermissionWithActionList)
		permissionList = append(permissionList, normalOrderPermissionList)
	}

	// 功能模块转换 -- APP用
	menuList := helper.GetMenuList(userInfo.Module)
	b,_ := json.Marshal(&menuList)
	userInfo.Module = string(b)

	// 用户角色获取对应的tabList--APP用
	if userInfo.IsAdmin == 3 {
		userInfo.TabList = result.NewTabListToPlace()
	} else {
		userInfo.TabList = result.NewTabListToAgent()
	}

	roleInfo.Permissions = permissionList
	userInfo.Role = roleInfo
	return
}

func (l *AuthLogic) GetWifiUserInfo(uid int) (userInfo *users.UserInfoWithLogin) {
	var permissionList []*Permissions.PsermissionWithActionList
	// 获取用户信息   (用户与角色 1对1的关系)
	userInfo = dao.NewUserDao().GetUserInfoFromId(uid).Unwrap().(*users.UserInfoWithLogin)
	// 获取角色信息
	roleInfo := dao.NewRoleDao().GetRoleInfoFromId(userInfo.RoleId).Unwrap().(*roles.RoleWithLogin)
	// 获取角色下的权限信息
	permissionList = dao.NewPermissionDao().GetPermissionsFromRoleId(userInfo.RoleId).Unwrap().([]*Permissions.PsermissionWithActionList)

	userInfo.TabList = result.NewTabListToWifiUser()

	roleInfo.Permissions = permissionList
	userInfo.Role = roleInfo
	return
}

func (l *AuthLogic) GetCountChildrenById(id int) int64 {
	total := dao.NewUserDao().CountPlaceUserByParentId(id).Unwrap().(int64)
	return total
}

// GetUserNav 获取用户导航业务逻辑
func (l *AuthLogic) GetUserNavList(uid int) (navList []*Menus.MenusModel) {
	// 获取用户信息
	userInfo := dao.NewUserDao().GetUserInfoFromId(uid).Unwrap().(*users.UserModel)
	// 获取用户所属角色下的 拥有的导航菜单
	navList = dao.GetUserNavList(userInfo.RoleID).Unwrap().([]*Menus.MenusModel)
	return
}

// 公众号商户登录逻辑
func (l *AuthLogic) UserLoginByPlace(phone, password, openid string, ip string) (*request.LoginBack, error) {
	loginTime := dingo.Time(time.Now().Unix())
	loginInfo := &request.LoginBack{
		Openid:   "",
		Token:    "",
		UserName: "",
		Avatar:   "",
	}
	user := dao.NewUserDao().GetUserInfoFromPhone(phone).Unwrap().(*users.UserModel)
	if openid == "" {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "微信未授权", phone)
		return loginInfo, errors.New("微信未授权") // 用户名不存在
	}
	if user.ID == 0 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "用户名不存在", phone)
		return loginInfo, errors.New("用户名密码错误") // 用户名不存在
	}
	if user.Password != utils.EncryptPassword(password) {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "密码错误", phone)
		return loginInfo, errors.New("密码错误") // 密码错误
	}

	if user.Status == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "用户已禁用", phone)
		return loginInfo, errors.New("该帐户已被禁用") // 用户已被禁用
	}
	//if user.IsAdmin == helper.TypeNumIsAdminAgent || user.IsAdmin == helper.TypeNumIsAdminStaff { // 只允许商户和代码商登录
	//	dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "不是商户帐号", phone)
	//	return loginInfo, errors.New("用户名密码错误") // 用户已被禁用
	//}
	if user.IsDelete == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "帐号已被删除", phone)
		return loginInfo, errors.New("该帐户已弃用，请联系管理员恢复") // 已删除
	}
	if user.IsBind == 1 && user.Openid != openid {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "绑定微信与登录微信不一致", phone) // 记录登录日志
		return loginInfo, errors.New("请使用绑定的微信登录")                                                         // 判断 绑定的微信号是否符合
	}

	// 获取access_token
	wxTokenKey := utils.Join("WxAccess-Token-", openid)
	accessToken := global.Rdb.Get(context.Background(), wxTokenKey).Val()

	// 获取用户信息
	resp, _ := authorized.GetUserInfo(accessToken, openid)
	log.Println("获取用户信息", resp)

	user.LoginCount = user.LoginCount + 1
	user.LastLoginTime = loginTime
	user.LastLoginIp = ip
	user.Openid = openid
	user.Avatar = resp.Headimgurl
	user.Country = resp.Country
	user.Province = resp.Province
	user.City = resp.City
	user.NickName = resp.Nickname
	//user.Address = resp.Address
	//user.WxMobile = resp.Mobile
	//user.WxName = resp.Name
	user.Unionid = resp.Unionid
	user.Sex = resp.Sex
	user.IsBind = 1

	dao.NewUserDao().UpdatePlaceUserById(user).Unwrap()
	log.Println("更新用户信息", user)

	// 生成 Token
	key := utils.Join("Yd-Wechat-Login-Token", strconv.Itoa(user.ID))
	token, err := dingo.GenerateToken(user.ID, user.UserName, user.IsAdmin, user.ParentID, user.IsPlace, user.IsDraw, "")
	global.Rdb.Set(context.Background(), key, token, time.Hour*1) // 过期时间1小时

	// 更新member中的 unionid
	dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "登录成功", phone) // 记录登录日志

	// 将此登录的商户名下的订单撤销

	loginInfo = &request.LoginBack{
		Openid:   openid,
		Token:    token,
		UserName: resp.Nickname,
		Avatar:   resp.Headimgurl,
	}
	log.Println("返回的用户信息", loginInfo)
	return loginInfo, err
}

// 商户微信登录
func (l *AuthLogic) UserWechatLogin(param *request.StewardAppUserAccountLoginRes) (*request.LoginBack, error) {
	loginTime := dingo.Time(time.Now().Unix())
	loginInfo := &request.LoginBack{}
	//user := dao.NewUserDao().GetUserInfoFromPhone(param.Phone).Unwrap().(*users.UserModel)
	user := dao.NewUserDao().GetUserInfoFromUnionIdInOpenId(param.WxUnionId).Unwrap().(*users.UserModel)
	phone := ""

	if user.ID == 0 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "用户名不存在", phone)
		return loginInfo, errors.New("未绑定登录帐号")
	}
	//if user.Password != utils.EncryptPassword(param.UserPwd) {
	//	dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "密码错误", phone)
	//	return loginInfo, errors.New("密码错误") // 密码错误
	//}
	if user.Status == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "用户已禁用", phone)
		return loginInfo, errors.New("该帐户已被禁用") // 用户已被禁用
	}
	if user.IsDelete == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "帐号已被删除", phone)
		return loginInfo, errors.New("该帐户已弃用，请联系管理员恢复") // 已删除
	}
	//if user.IsBind == 1 && user.Openid != "" && user.Openid != param.WxOpenid {
	//	dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "绑定微信与登录微信不一致", phone) // 记录登录日志
	//	return loginInfo, errors.New("请使用绑定的微信登录")
	//}

	user.LoginCount = user.LoginCount + 1
	user.LastLoginTime = loginTime
	user.LastLoginIp = param.Ip

	dao.NewUserDao().UpdateUserById(user).Unwrap()

	// 生成 Token
	key := utils.Join("Yd-Wechat-Login-Token", strconv.Itoa(user.ID))
	token, err := dingo.GenerateToken(user.ID, user.UserName, user.IsAdmin, user.ParentID, user.IsPlace, user.IsDraw, "")
	global.Rdb.Set(context.Background(), key, token, time.Hour*1) // 过期时间1小时

	// 更新member中的 unionid
	dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "登录成功", phone) // 记录登录日志

	loginInfo = &request.LoginBack{
		Openid:   user.Openid,
		Token:    token,
		UserName: user.UserName,
		Avatar:   user.Avatar,
	}
	return loginInfo, err
}

// 商户帐号登录
func (l *AuthLogic) UserAccountLogin(param *request.StewardAppUserAccountLoginRes) (*request.LoginBack, error) {
	loginTime := dingo.Time(time.Now().Unix())
	loginInfo := &request.LoginBack{}
	user := dao.NewUserDao().GetUserInfoFromPhoneInOpenId(param.Phone).Unwrap().(*users.UserModel)
	phone := param.Phone

	if user.ID == 0 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "APP登录", "用户名不存在", phone)
		return loginInfo, errors.New("用户名不存在") // 用户名不存在
	}
	if user.Password != utils.EncryptPassword(param.UserPwd) {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "APP登录", "密码错误", phone)
		return loginInfo, errors.New("密码错误") // 密码错误
	}
	if user.Status == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "APP登录", "用户已禁用", phone)
		return loginInfo, errors.New("该帐户已被禁用") // 用户已被禁用
	}
	if user.IsDelete == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "APP登录", "帐号已被删除", phone)
		return loginInfo, errors.New("该帐户已弃用，请联系管理员恢复") // 已删除
	}
	if user.IsBind == 1 && user.Openid != "" && user.Openid != param.WxOpenid {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "APP登录", "绑定微信与登录微信不一致", phone) // 记录登录日志
		return loginInfo, errors.New("请使用绑定的微信登录")
	}
	// 2.0帐号才可以登录
	if user.IsSteward != 1 {
		if !helper.InSlice(strings.Split(user.Platform, ","), "hotel") {
			dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "APP登录", "无平台登录权限，请联系管理员", phone)
			return loginInfo, errors.New("无平台登录权限，请联系管理员")
		}
		//dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "APP登录", "非B端运营平台人员", phone)
		//return loginInfo, errors.New("非B端运营平台人员")
	}

	user.LoginCount = user.LoginCount + 1
	user.LastLoginTime = loginTime
	user.LastLoginIp = param.Ip

	if param.WxOpenid != "" {
		user.Openid = param.WxOpenid
		user.Unionid = param.WxUnionId
	}

	dao.NewUserDao().UpdateUserById(user).Unwrap()
	dao.NewUserDao().InsertWechatUserRelevancy(user, global.Cfg.Wx.AppId)

	// 生成 Token
	key := utils.Join("Yd-Wechat-Login-Token", strconv.Itoa(user.ID))
	token, err := dingo.GenerateToken(user.ID, user.UserName, user.IsAdmin, user.ParentID, user.IsPlace, user.IsDraw, "")
	global.Rdb.Set(context.Background(), key, token, time.Hour*12) // 过期时间1小时

	// 更新member中的 unionid
	dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "APP登录", "登录成功", phone) // 记录登录日志

	loginInfo = &request.LoginBack{
		Openid:   user.Openid,
		Token:    token,
		UserName: user.UserName,
		Avatar:   user.Avatar,
	}
	return loginInfo, err
}

// 短信登录
func (l *AuthLogic) UserSmsCodeLogin(param *request.StewardAppUserAccountLoginRes) (*request.LoginBack, error) {
	loginTime := dingo.Time(time.Now().Unix())
	loginInfo := &request.LoginBack{}
	user := dao.NewUserDao().GetUserInfoFromPhoneInOpenId(param.Phone).Unwrap().(*users.UserModel)

	if user.ID == 0 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "用户名不存在")
		return loginInfo, errors.New("用户名不存在")
	}
	if checkInt := dao.NewUserDao().GetSmsCodeInfo(param.Phone, param.Code).Unwrap().(int64); checkInt <= 0 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "验证码错误")
		return loginInfo, errors.New("验证码错误")
	}
	if user.Status == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "用户已禁用")
		return loginInfo, errors.New("该帐户已被禁用") // 用户已被禁用
	}
	if user.IsDelete == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "帐号已被删除")
		return loginInfo, errors.New("该帐户已弃用，请联系管理员恢复") // 已删除
	}
	if user.IsBind == 1 && user.Openid != "" && user.Openid != param.WxOpenid {
		dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "绑定微信与登录微信不一致") // 记录登录日志
		return loginInfo, errors.New("请使用绑定的微信登录")
	}

	user.LoginCount = user.LoginCount + 1
	user.LastLoginTime = loginTime
	user.LastLoginIp = param.Ip

	dao.NewUserDao().UpdateUserById(user).Unwrap()

	// 生成 Token
	key := utils.Join("Yd-Wechat-Login-Token", strconv.Itoa(user.ID))
	token, err := dingo.GenerateToken(user.ID, user.UserName, user.IsAdmin, user.ParentID, user.IsPlace, user.IsDraw, "")
	global.Rdb.Set(context.Background(), key, token, time.Hour*1) // 过期时间1小时

	// 更新member中的 unionid
	dingo.Task(l.insertUserLoginLog, func() {}, user, param.Ip, loginTime, "公众号商户登录", "登录成功") // 记录登录日志

	loginInfo = &request.LoginBack{
		Openid:   user.Openid,
		Token:    token,
		UserName: user.UserName,
		Avatar:   user.Avatar,
	}
	return loginInfo, err
}

// 公众号用户签名登录
func (l *AuthLogic) UserSignLogin(phone, password, openid string, ip string) (*request.Sign, error) {
	loginTime := dingo.Time(time.Now().Unix())
	loginInfo := &request.Sign{
		UserId:   0,
		Openid:   "",
		Token:    "",
		UserName: "",
		Avatar:   "",
	}
	user := dao.NewUserDao().GetUserInfoFromPhone(phone).Unwrap().(*users.UserModel)
	if openid == "" {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "微信未授权", phone)
		return loginInfo, errors.New("微信未授权") // 用户名不存在
	}
	if user.ID == 0 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "用户名不存在", phone)
		return loginInfo, errors.New("用户名密码错误") // 用户名不存在
	}
	if user.Password != utils.EncryptPassword(password) {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "密码错误", phone)
		return loginInfo, errors.New("密码错误") // 密码错误
	}

	if user.Status == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "用户已禁用", phone)
		return loginInfo, errors.New("该帐户已被禁用") // 用户已被禁用
	}
	if user.IsAdmin != 3 && user.IsAdmin != 2 { // 只允许商户和代码商登录
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "不是商户帐号", phone)
		return loginInfo, errors.New("用户名密码错误") // 用户已被禁用
	}
	if user.IsDelete == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号商户登录", "帐号已被删除", phone)
		return loginInfo, errors.New("该帐户已弃用，请联系管理员恢复") // 已删除
	}

	// 获取access_token
	wxTokenKey := utils.Join("WxAccess-Token-", openid)
	accessToken := global.Rdb.Get(context.Background(), wxTokenKey).Val()

	// 获取用户信息
	resp, _ := authorized.GetUserInfo(accessToken, openid)
	log.Println("获取用户信息", resp)

	user.LoginCount = user.LoginCount + 1
	user.LastLoginTime = loginTime
	user.LastLoginIp = ip
	user.Openid = openid
	user.Avatar = resp.Headimgurl
	user.Country = resp.Country
	user.Province = resp.Province
	user.City = resp.City
	user.NickName = resp.Nickname
	//user.Address = resp.Address
	//user.WxMobile = resp.Mobile
	//user.WxName = resp.Name
	user.Unionid = resp.Unionid
	user.Sex = resp.Sex
	user.IsBind = 1

	dao.NewUserDao().UpdatePlaceUserById(user).Unwrap()
	log.Println("更新用户信息", user)

	// 生成 Token
	key := utils.Join("Yd-Wechat-Login-Token", strconv.Itoa(user.ID))
	token, err := dingo.GenerateToken(user.ID, user.UserName, user.IsAdmin, user.ParentID, user.IsPlace, user.IsDraw, "")
	global.Rdb.Set(context.Background(), key, token, time.Hour*1) // 过期时间1小时

	dingo.Task(l.insertUserLoginLog, func() {}, user, ip, loginTime, "公众号登录", "登录成功", phone) // 记录登录日志

	loginInfo = &request.Sign{
		UserId:   user.ID,
		Openid:   openid,
		Token:    token,
		UserName: resp.Nickname,
		Avatar:   resp.Headimgurl,
	}
	log.Println("返回的用户信息", loginInfo)
	return loginInfo, err
}

// 恢复公众号登录的订单
func (l *AuthLogic) ResumeOrder(param ...interface{}) {
	phone := param[0].(string)
	//openid := param[1].(string)
	userInfo := dao.NewUserDao().GetUserInfoFromPhone(phone).Unwrap().(*users.UserModel)

	// 获取该用户的会员信息
	memberInfo := memberdao.NewMemberDao().GetMemberInfoByOpenidOrUnionid("", userInfo.Unionid).Unwrap().(*membermodel.MembersModel)

	var orderLists []*orders.OrderModel
	global.Orm.Table("orders").
		Where("member_id = ?", memberInfo.UUID).
		Where("is_draw = ?", 1).
		Where("is_tianhai = ?", 0).
		Find(&orderLists)

	for _, lst := range orderLists {
		devInfo := dao.NewDeviceDao().FetchDeviceInfoWithType(lst.DeviceSn).Unwrap().(*devices.DeviceType)
		if lst.State == 5 {
			dingo.Task(NewOrderLogic().CalOrderDividends, func() {}, lst, devInfo, lst.SettlementMoney, int64(lst.EndAt)) // 计算分红 - 异步任务
		}

		dao.NewOrderDao().UpdateOrderIsDraw(lst)
	}
}


func (l *AuthLogic) ZfbUserLogin(param *request.ZfbUserLoginReq) (
	xmSaleUserInfo *userresp.PlaceUserInfo, err error) {
	ip := param.Ip
	phone := param.UserName
	password := param.UserPwd
	loginTime := dingo.Time(time.Now().Unix())

	// 获取用户信息
	xmSaleUserInfo = userdao.NewUserDao().GetPlaceUserInfoByPhone(phone).Unwrap().(*userresp.PlaceUserInfo)
	userInfo := &users.UserModel{}
	userInfo.ID = xmSaleUserInfo.UserId
	userInfo.IsAdmin = xmSaleUserInfo.IsAdmin
	userInfo.UserName = xmSaleUserInfo.UserName
	userInfo.ParentID = xmSaleUserInfo.ParentID

	if xmSaleUserInfo.UserId == 0 {
		dingo.Task(l.insertUserLoginLog, func() {}, userInfo, ip, loginTime, "支付宝登录", "用户名错误", phone)
		return nil, errors.New("用户名密码错误") // 用户名不存在
	}
	if xmSaleUserInfo.Status == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, userInfo, ip, loginTime, "支付宝登录", "帐户已被禁用", phone)
		return nil, errors.New("该帐户已被禁用") // 用户已被禁用
	}
	if xmSaleUserInfo.IsDelete == 2 {
		dingo.Task(l.insertUserLoginLog, func() {}, userInfo, ip, loginTime, "支付宝登录", "帐号已弃用", phone)
		return nil, errors.New("该帐户已弃用，请联系管理员恢复") // 已删除
	}
	if xmSaleUserInfo.Password != utils.EncryptPassword(password) {
		dingo.Task(l.insertUserLoginLog, func() {}, userInfo, ip, loginTime, "支付宝登录", "密码错误", phone)
		return nil, errors.New("用户名密码错误") // 密码错误
	}

	// 生成 Token
	key := utils.Join("Token", "-", "zfb", "-", "Login-Token-", strconv.Itoa(xmSaleUserInfo.UserId))
	token, err := dingo.GenerateToken(xmSaleUserInfo.UserId, xmSaleUserInfo.Name, xmSaleUserInfo.IsAdmin, xmSaleUserInfo.ParentID, 0, 0, "")
	global.Rdb.Set(context.Background(), key, token, time.Hour*24)

	dingo.Task(l.updateUserLoginInfo, func() {}, userInfo.ID, ip, loginTime)                          // 更新登录信息
	dingo.Task(l.updateUserLoginCount, func() {}, userInfo.ID)                                        // 更新登录次数
	dingo.Task(l.insertUserLoginLog, func() {}, userInfo, ip, loginTime, "支付宝登录", "登录成功", phone) // 记录登录日志

	xmSaleUserInfo.Token = token
	return
}
